using Lzfy_Refund_Service.Models;
using Lzfy_Refund_Service.Repositories;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System.Text.Json;
using System.Text.Encodings.Web;
using System.Text.Unicode;

namespace Lzfy_Refund_Service.Services
{
    /// <summary>
    /// 门诊患者就诊信息服务实现类
    /// </summary>
    public class OutpPatientVisitService : IOutpPatientVisitService
    {
        private readonly IOutpPatientVisitRepository _outpPatientVisitRepository;
        private readonly IRedisService _redisService;
        private readonly ILogger<OutpPatientVisitService> _logger;
        private readonly IConfiguration _configuration;
        private readonly TimeSpan _keyExpiration;

        public OutpPatientVisitService(
            IOutpPatientVisitRepository outpPatientVisitRepository,
            IRedisService redisService,
            ILogger<OutpPatientVisitService> logger,
            IConfiguration configuration)
        {
            _outpPatientVisitRepository = outpPatientVisitRepository;
            _redisService = redisService;
            _logger = logger;
            _configuration = configuration;
            
            var expirationMinutes = _configuration.GetValue<int>("Redis:KeyExpirationMinutes", 10);
            _keyExpiration = TimeSpan.FromMinutes(expirationMinutes);
        }

        /// <summary>
        /// 同步最近10分钟内的门诊患者就诊信息到Redis
        /// </summary>
        /// <returns>同步的数据条数</returns>
        public async Task<int> SyncRecentOutpPatientVisitsToRedisAsync()
        {
            try
            {
                _logger.LogInformation("开始同步门诊患者就诊信息到Redis");
                
                // 从数据库获取最新数据
                var visits = await _outpPatientVisitRepository.GetRecentOutpPatientVisitsAsync();
                var visitList = visits.ToList();
                
                if (!visitList.Any())
                {
                    _logger.LogInformation("没有找到需要同步的门诊患者就诊信息");
                    return 0;
                }
                
                // 记录查询到的数据详情
                _logger.LogInformation("查询到 {Count} 条门诊患者就诊信息", visitList.Count);                
                // 过滤出有效的数据（DOCTOR_VS_OUTP_VISIT_ID不为空且不为null）
                var validVisits = visitList.Where(v => !string.IsNullOrEmpty(v.DOCTOR_VS_OUTP_VISIT_ID)).ToList();
                
                //_logger.LogInformation("有效的DOCTOR_VS_OUTP_VISIT_ID键数量: {Count}", validVisits.Count);
                
                if (validVisits.Count == 0)
                {
                    _logger.LogWarning("没有有效的DOCTOR_VS_OUTP_VISIT_ID键，无法同步到Redis");
                    return 0;
                }
                
                // 获取所有键，用于批量检查是否已存在
                var keys = validVisits.Select(v => v.DOCTOR_VS_OUTP_VISIT_ID).ToList();
                
                // 批量检查哪些键已经存在（只检查db1）
                _logger.LogInformation("开始批量检查Redis db1中已存在的键");
                
                // 检查db1中已存在的键
                var existingKeysDb1 = await _redisService.BatchExistsAsync(keys);
                var existingKeysDb1Set = new HashSet<string>(existingKeysDb1);
                
                // 过滤出需要新增的数据（只要db1中不存在就可以插入）
                var newVisits = validVisits.Where(v => !existingKeysDb1Set.Contains(v.DOCTOR_VS_OUTP_VISIT_ID)).ToList();
                
                if (!newVisits.Any())
                {
                    _logger.LogInformation("所有数据都已存在于Redis db1中，跳过同步。总数据: {Total}, 有效数据: {Valid}, db1已存在: {Db1Existing}", 
                        visitList.Count, validVisits.Count, existingKeysDb1.Count);
                    return 0;
                }
                
                // 同步新数据到Redis
                int syncedCount = 0;
                foreach (var visit in newVisits)
                {
                    try
                    {
                        var json = JsonSerializer.Serialize(visit, new JsonSerializerOptions
                        {
                            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                            WriteIndented = false,
                            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
                        });
                        
                        var success = await _redisService.SetAsync(visit.DOCTOR_VS_OUTP_VISIT_ID!, json, _keyExpiration);
                        
                        if (success)
                        {
                            syncedCount++;
                            _logger.LogInformation("成功同步数据到Redis，键: '{Key}', 患者: {PatientName}", 
                                visit.DOCTOR_VS_OUTP_VISIT_ID, visit.PATI_NAME);
                        }
                        else
                        {
                            _logger.LogWarning("同步数据到Redis失败，键: '{Key}', 患者: {PatientName}", 
                                visit.DOCTOR_VS_OUTP_VISIT_ID, visit.PATI_NAME);
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "同步单条数据到Redis异常，键: {Key}", visit.DOCTOR_VS_OUTP_VISIT_ID);
                    }
                }
                
                _logger.LogInformation("门诊患者就诊信息同步完成。总数据: {Total}, 有效数据: {Valid}, db1已存在: {Db1Existing}, 新同步: {Synced}", 
                    visitList.Count, validVisits.Count, existingKeysDb1.Count, syncedCount);
                
                return syncedCount;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "同步门诊患者就诊信息到Redis失败");
                return 0;
            }
        }

        /// <summary>
        /// 从Redis获取门诊患者就诊信息
        /// </summary>
        /// <param name="doctorVsOutpVisitId">医生与门诊就诊ID组合键</param>
        /// <returns>门诊患者就诊信息</returns>
        public async Task<OutpPatientVisit?> GetFromRedisAsync(string doctorVsOutpVisitId)
        {
            try
            {
                if (string.IsNullOrEmpty(doctorVsOutpVisitId))
                {
                    _logger.LogWarning("DoctorVsOutpVisitId为空，无法从Redis获取数据");
                    return null;
                }
                
                var json = await _redisService.GetAsync(doctorVsOutpVisitId);
                
                if (string.IsNullOrEmpty(json))
                {
                    _logger.LogDebug("Redis中不存在键: {Key}", doctorVsOutpVisitId);
                    return null;
                }
                
                var visit = JsonSerializer.Deserialize<OutpPatientVisit>(json, new JsonSerializerOptions
                {
                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
                });
                
                _logger.LogDebug("成功从Redis获取数据，键: {Key}", doctorVsOutpVisitId);
                return visit;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "从Redis获取门诊患者就诊信息失败，键: {Key}", doctorVsOutpVisitId);
                return null;
            }
        }

        /// <summary>
        /// 获取最近10分钟内的门诊患者就诊信息（直接从数据库查询）
        /// </summary>
        /// <returns>门诊患者就诊信息列表</returns>
        public async Task<IEnumerable<OutpPatientVisit>> GetRecentOutpPatientVisitsAsync()
        {
            try
            {
                _logger.LogInformation("开始从数据库查询最近10分钟内的门诊患者就诊信息");
                
                var visits = await _outpPatientVisitRepository.GetRecentOutpPatientVisitsAsync();
                var visitList = visits.ToList();
                
                _logger.LogInformation("成功查询到 {Count} 条门诊患者就诊信息", visitList.Count);
                
                return visitList;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "从数据库查询门诊患者就诊信息失败");
                return Enumerable.Empty<OutpPatientVisit>();
            }
        }
    }
}